﻿Public Class frmOR
    Dim intVariableCount As Integer = 2
    Dim intConstraintCount As Integer = 1
    Const intXIncrement As Integer = 67
    Const intYIncrement As Integer = 31
    Dim intLabelSize As New System.Drawing.Size(29, 13)
    Dim intTextBoxSize As New System.Drawing.Size(23, 20)
    Dim lstTextBoxes As New List(Of TextBox)
    Dim lstLabels As New List(Of Label)
    Dim lstZRowText As New List(Of TextBox)
    Dim lstCBO As New List(Of ComboBox)
    Dim lstRHS As New List(Of TextBox)
    Dim lMax As Boolean = True
    Dim lSolved As Boolean = False
    Dim lTwoPhase As Boolean = False
    Dim lPhase1Complete As Boolean = True

    Private Sub frmOR_Load(sender As System.Object, e As System.EventArgs) Handles MyBase.Load
        lstZRowText.Add(txtX1)
        lstZRowText.Add(txtX2)
        lstTextBoxes.Add(txtC1X1)
        lstTextBoxes.Add(txtC1X2)
        lstLabels.Add(lblX1)
        lstLabels.Add(lblX2)
        lstLabels.Add(lblBX1)
        lstLabels.Add(lblBX2)
        lstLabels.Add(lblC1X1)
        lstLabels.Add(lblC1X2)
        lstCBO.Add(cboC1)
        lstRHS.Add(txtC1)
    End Sub

    Private Sub btnAddVariable_Click(sender As System.Object, e As System.EventArgs) Handles btnAddVariable.Click
        intVariableCount += 1
        For Each ctrl As Control In Me.Controls
            If ctrl.GetType() = GetType(Label) Then
                Dim ctrlName As String = DirectCast(ctrl, Label).Name
                If ctrlName = "lblX" & (intVariableCount - 1).ToString Then
                    DirectCast(ctrl, Label).Text &= " +"
                ElseIf ctrlName.Substring(0, 4) = "lblC" AndAlso ctrlName.EndsWith("X" & (intVariableCount - 1).ToString) Then
                    DirectCast(ctrl, Label).Text &= " +"
                ElseIf ctrlName = "lblBX" & (intVariableCount - 1).ToString Then
                    DirectCast(ctrl, Label).Text &= ","
                End If
            End If
        Next
        Me.Size = New System.Drawing.Size(Me.Size.Width + intXIncrement, Me.Size.Height)
        AddVarLabels()
        AddVarTextBoxes()
    End Sub
    Private Sub AddVarLabels()
        Dim lblXNew As New Label
        lblXNew.Size = intLabelSize
        lblXNew.Location = New System.Drawing.Point(lblX1.Location.X + (intVariableCount - 1) * intXIncrement, lblX1.Location.Y)
        lblXNew.Text = "X" & intVariableCount
        lblXNew.Name = "lblX" & intVariableCount
        Me.Controls.Add(lblXNew)
        lstLabels.Add(lblXNew)
        Dim lstNewLabels As New List(Of Label)
        For i As Integer = 1 To intConstraintCount
            For Each ctrl As Label In lstLabels
                If ctrl.Name = ("lblC" & i.ToString & "X1") Then
                    Dim lblCXNew As New Label
                    lblCXNew.Size = intLabelSize
                    lblCXNew.Location = New System.Drawing.Point(ctrl.Location.X + (intVariableCount - 1) * intXIncrement, ctrl.Location.Y)
                    lblCXNew.Text = "X" & intVariableCount
                    lblCXNew.Name = "lblC" & i.ToString & "X" & intVariableCount
                    Me.Controls.Add(lblCXNew)
                    lstNewLabels.Add(lblCXNew)
                    'Exit For
                ElseIf ctrl.Name = "lblBX1" Then
                    Dim lblBXNew As New Label
                    lblBXNew.Size = intLabelSize
                    lblBXNew.Location = New System.Drawing.Point(ctrl.Location.X + (intVariableCount - 1) * intXIncrement, ctrl.Location.Y)
                    lblBXNew.Text = "X" & intVariableCount
                    lblBXNew.Name = "lblBX" & intVariableCount
                    lblBXNew.Anchor = CType((System.Windows.Forms.AnchorStyles.Bottom Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
                    Me.Controls.Add(lblBXNew)
                    lstNewLabels.Add(lblBXNew)
                End If
            Next
        Next
        For Each lab As Label In lstNewLabels
            lstLabels.Add(lab)
        Next
    End Sub
    Private Sub AddVarTextBoxes()
        Dim txtXNew As New TextBox
        txtXNew.Size = intTextBoxSize
        txtXNew.Location = New System.Drawing.Point(txtX1.Location.X + (intVariableCount - 1) * intXIncrement, txtX1.Location.Y)
        txtXNew.Name = "txtX" & intVariableCount
        txtXNew.TabIndex = 9 + intVariableCount
        Me.Controls.Add(txtXNew)
        lstZRowText.Add(txtXNew)
        AddHandler txtXNew.Enter, AddressOf TextBox_Enter
        Dim lstNewText As New List(Of TextBox)
        For i As Integer = 1 To intConstraintCount
            For Each ctrl As TextBox In lstTextBoxes

                If ctrl.Name = ("txtC" & i.ToString & "X1") Then
                    Dim txtCXNew As New TextBox
                    txtCXNew.Size = intTextBoxSize
                    txtCXNew.Location = New System.Drawing.Point(ctrl.Location.X + (intVariableCount - 1) * intXIncrement, ctrl.Location.Y)
                    txtCXNew.Name = "txtC" & i.ToString & "X" & intVariableCount
                    txtCXNew.TabIndex = ctrl.TabIndex + 1
                    Me.Controls.Add(txtCXNew)
                    lstNewText.Add(txtCXNew)
                    'Exit For
                End If

            Next
        Next
        For Each txt As TextBox In lstNewText
            lstTextBoxes.Add(txt)
            AddHandler txt.Enter, AddressOf TextBox_Enter
        Next
    End Sub
    Private Sub AddConstLabels()
        Dim lstNewLabels As New List(Of Label)
        For i As Integer = 1 To intVariableCount
            For Each ctrl As Label In lstLabels

                If ctrl.Name = ("lblC1X" & i.ToString) Then
                    Dim lblCXNew As New Label
                    lblCXNew.Size = intLabelSize
                    lblCXNew.Location = New System.Drawing.Point(ctrl.Location.X, ctrl.Location.Y + (intConstraintCount - 1) * intYIncrement)
                    lblCXNew.Text = "X" & i.ToString
                    lblCXNew.Name = "lblC" & intConstraintCount & "X" & i.ToString
                    If lblCXNew.Name <> "lblC" & intConstraintCount & "X" & intVariableCount.ToString Then
                        lblCXNew.Text &= " +"
                    End If
                    Me.Controls.Add(lblCXNew)
                    lstNewLabels.Add(lblCXNew)
                    'Exit For
                End If

            Next
        Next
        For Each lab As Label In lstNewLabels
            lstLabels.Add(lab)
        Next
    End Sub
    Private Sub AddConstTextBoxes()
        Dim lstNewText As New List(Of TextBox)
        For i As Integer = 1 To intVariableCount
            For Each ctrl As TextBox In lstTextBoxes

                If ctrl.Name = ("txtC1X" & i.ToString) Then
                    Dim txtCXNew As New TextBox
                    txtCXNew.Size = intTextBoxSize
                    txtCXNew.Location = New System.Drawing.Point(ctrl.Location.X, ctrl.Location.Y + (intConstraintCount - 1) * intYIncrement)
                    txtCXNew.Name = "txtC" & intConstraintCount & "X" & i.ToString
                    txtCXNew.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Left), System.Windows.Forms.AnchorStyles)
                    txtCXNew.TabIndex = 9 + (20 * intConstraintCount) + i
                    Me.Controls.Add(txtCXNew)
                    lstNewText.Add(txtCXNew)
                    'Exit For
                End If
            Next
        Next

        Dim txtCNew As New TextBox
        txtCNew.Size = txtC1.Size
        txtCNew.Location = New System.Drawing.Point(txtC1.Location.X, txtC1.Location.Y + (intConstraintCount - 1) * intYIncrement)
        txtCNew.Name = "txtC" & intConstraintCount
        txtCNew.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        txtCNew.TabIndex = 29 + (20 * intConstraintCount)
        Me.Controls.Add(txtCNew)
        lstRHS.Add(txtCNew)

        Dim cboCNew As New ComboBox
        cboCNew.Size = cboC1.Size
        cboCNew.Location = New System.Drawing.Point(cboC1.Location.X, cboC1.Location.Y + (intConstraintCount - 1) * intYIncrement)
        Dim items As String() = {"<=", "=", ">="}
        cboCNew.Items.AddRange(items)
        cboCNew.Name = "cboC" & intConstraintCount
        cboCNew.Anchor = CType((System.Windows.Forms.AnchorStyles.Top Or System.Windows.Forms.AnchorStyles.Right), System.Windows.Forms.AnchorStyles)
        cboCNew.TabIndex = 28 + (20 * intConstraintCount)
        cboCNew.Text = "<="
        Me.Controls.Add(cboCNew)
        lstCBO.Add(cboCNew)

        For Each txt As TextBox In lstNewText
            lstTextBoxes.Add(txt)
            AddHandler txt.Enter, AddressOf TextBox_Enter
        Next

    End Sub
    Private Sub btnConstraint_Click(sender As System.Object, e As System.EventArgs) Handles btnConstraint.Click
        intConstraintCount += 1

        Me.Size = New System.Drawing.Size(Me.Size.Width, Me.Size.Height + intYIncrement)
        AddConstLabels()
        AddConstTextBoxes()

    End Sub

    Private Sub btnSolve_Click(sender As System.Object, e As System.EventArgs) Handles btnSolve.Click
        If Solve() Then
            btnView.Enabled = True
        End If

    End Sub
    Private Function Solve() As Boolean
        ds.Tables.Clear()
        ds.Clear()
        FillInitial()
        nSteps = 0
        lSolved = False
        If lTwoPhase Then
            Do Until lPhase1Complete = True Or lInfeasible
                nSteps += 1
                lPhase1Complete = TwoPhase.PhaseOne(ds.Tables(ds.Tables.Count - 1))
            Loop
            nSteps = 0
            Do Until lSolved = True Or lInfeasible
                nSteps += 1
                lSolved = TwoPhase.Solve(ds.Tables(ds.Tables.Count - 1), False)
            Loop

        Else
            Do Until lSolved = True
                nSteps += 1
                lSolved = SimplexAlgorithm.Solve(ds.Tables(ds.Tables.Count - 1))
            Loop
        End If
        Dim Solution As String = "Optimal Solution:" & vbCrLf
        For Each dr As DataRow In ds.Tables(ds.Tables.Count - 1).Rows
            Solution += dr("Basic") & " = " & dr("RHS") & vbCrLf
        Next
        Solution += ""
        If lInfeasible Then
            MsgBox("The current problem is infeasible", MsgBoxStyle.OkOnly, "Infeasible")
        Else
            MsgBox(Solution, MsgBoxStyle.OkOnly, "Solution Found!")
        End If
        Return True
    End Function

    Private Sub btnView_Click(sender As System.Object, e As System.EventArgs) Handles btnView.Click
        Dim frmViewResults As New frmResults
        frmViewResults.ShowDialog()
    End Sub

    Private Sub rbtMax_CheckedChanged(ByVal sender As System.Object, ByVal e As System.EventArgs) Handles rbtMax.CheckedChanged, rbtMin.CheckedChanged
        If rbtMax.Checked Then
            lMax = True
        Else
            lMax = False
        End If
    End Sub
    Private Sub FillInitial()
        Dim dt As New DataTable("Initial")
        dt.Columns.Add("Basic", GetType(String), "")
        For i As Integer = 1 To intVariableCount
            dt.Columns.Add("X" & i.ToString, GetType(Decimal))
        Next
        Dim dr As DataRow = dt.NewRow

        For j As Integer = 1 To intVariableCount
            For Each ctrl As TextBox In lstZRowText
                If ctrl.Name = "txtX" & j.ToString Then
                    dr.Item("X" & j.ToString) = IIf(ctrl.Text.Trim = "", 0, CDec(ctrl.Text) * IIf(lMax, -1, 1))
                    Exit For
                End If
            Next
        Next
        dt.Columns.Add("RHS", GetType(Decimal))
        dt.Columns.Add("Ratio", GetType(Decimal))
        dt.Rows.Add(dr)
        For k As Integer = 1 To intConstraintCount
            Dim row As DataRow = dt.NewRow
            For j As Integer = 1 To intVariableCount
                For Each ctrl As TextBox In lstTextBoxes
                    If ctrl.Name = "txtC" & k.ToString & "X" & j.ToString Then
                        row.Item("X" & j.ToString) = IIf(ctrl.Text.Trim = "", 0, ctrl.Text)
                        Exit For
                    End If
                Next
            Next
            For Each txt As TextBox In lstRHS
                If txt.Name = "txtC" & k.ToString Then
                    row!RHS = IIf(txt.Text.Trim = "", 0, txt.Text)
                    Exit For
                End If
            Next
            For Each cb As ComboBox In lstCBO
                If cb.Name = "cboC" & k.ToString Then
                    If cb.Text = "<=" Then
                        dt.Columns.Add("S" & k.ToString, GetType(Decimal))
                        row.Item("S" & k.ToString) = 1
                        row.Item("Basic") = "S" & k.ToString
                    ElseIf cb.Text = ">=" Then
                        dt.Columns.Add("S" & k.ToString, GetType(Decimal))
                        row.Item("S" & k.ToString) = -1
                        row.Item("Basic") = "S" & k.ToString
                        dt.Columns.Add("A" & k.ToString, GetType(Decimal))
                        row.Item("A" & k.ToString) = 1
                        row.Item("Basic") = "A" & k.ToString
                        lPhase1Complete = False
                        lTwoPhase = True
                    ElseIf cb.Text = "=" Then
                        dt.Columns.Add("A" & k.ToString, GetType(Decimal))
                        row.Item("A" & k.ToString) = 1
                        row.Item("Basic") = "A" & k.ToString
                        lPhase1Complete = False
                        lTwoPhase = True
                    End If
                    Exit For
                End If
            Next
            dt.Rows.Add(row)
            dt.AcceptChanges()
        Next
        Dim w As Integer = 0
        ReorderColumns(dt)
        'dt.Columns("RHS").SetOrdinal(dt.Columns.Count - 1)
        'dt.Columns("Ratio").SetOrdinal(dt.Columns.Count - 1)
        dr!RHS = 0
        dr!Ratio = -1
        dr!Basic = "Z"
        FixBlanks(dt)
        ds.Tables.Add(dt)
        ds.AcceptChanges()
    End Sub

    Private Sub TextBox_Enter(sender As Object, e As System.EventArgs) Handles txtX1.Enter, txtX2.Enter, txtC1X1.Enter, txtC1X2.Enter, txtC1.Enter
        DirectCast(sender, TextBox).SelectAll()
    End Sub

    Private Sub btnReset_Click(sender As System.Object, e As System.EventArgs) Handles btnReset.Click
        Dim frmNew As New frmOR
        frmNew.Location = Me.Location
        frmNew.Show()
        Me.Close()
    End Sub
End Class
